package com.wolfeyes.common.utils.network.jsonbean;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * @description 获取对象信息工具类
 * @projectName film
 * @author yanyl
 * @email yanyljava@qq.com
 * @date 2018-07-11 15:53:58
 * @version 1.0.0
 */
public abstract class BeanUtils {
	
	/**
	 * Copy the property values of the given source bean into the target bean.
	 * <p>Note: The source and target classes do not have to match or even be derived
	 * from each other, as long as the properties match. Any bean properties that the
	 * source bean exposes but the target bean does not will silently be ignored.
	 * <p>This is just a convenience method. For more complex transfer needs,
	 * consider using a full BeanWrapper.
	 * @param source the source bean
	 * @param target the target bean
	 * @throws BeansException if the copying failed
	 * @see BeanWrapper
	 */
	@SuppressWarnings("unchecked")
	public static  <T> T cloneTo(T source) throws RuntimeException {
		
		//浅克隆（shallow clone）和深克隆（deep clone）
		//参考博客：https://blog.csdn.net/kenthong/article/details/5758884
		//参考博客：https://blog.csdn.net/xiaomingdetianxia/article/details/74453033
		ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
		
		ObjectOutputStream objectOutputStream = null;
		ObjectInputStream objectInputStream = null;
		
		// 目标对象
		T dist = null;
		
		try {
			objectOutputStream = new ObjectOutputStream(memoryBuffer);
			
			//将指定的对象写入流中，以便相应的 readObject() 方法可以恢复它
			objectOutputStream.writeObject(source);
			
			// 刷新该流的缓冲区。此操作将写入所有已缓冲的输出字节。
			objectOutputStream.flush();
			
			objectInputStream = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
			
			//从流中读取对象
			dist = (T) objectInputStream.readObject();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (objectOutputStream != null)
				try {
					objectOutputStream.close();
					objectOutputStream = null;
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			if (objectInputStream != null)
				try {
					objectInputStream.close();
					objectInputStream = null;
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
		}
		
		//返回克隆对象
		return dist;
	}
	
}

